package org.mathcloud.math.core.scilab.quantity;

import org.mathcloud.math.core.common.quantity.QuantityObject;
import org.mathcloud.math.core.common.quantity.RealMatrix;
import org.mathcloud.math.core.common.quantity.RealNumber;
import org.mathcloud.math.core.generic.quantity.GenericRealNumber;
import org.mathcloud.math.core.generic.signature.GenericQuantityObjectSignature;
import org.scilab.modules.javasci.JavasciException;
import org.scilab.modules.types.ScilabDouble;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ScilabRealMatrix extends ScilabQuantityObject implements
		RealMatrix
{	
	public ScilabRealMatrix(Integer rows,Integer cols)
	{
		super();
		try
		{
			sciObject = new ScilabDouble(new double[rows][cols]);
			sciEngine.put(sciVarName, sciObject);
		} catch (JavasciException e)
		{
			log.error("Constructor - ",e);
		}
		signature = GenericQuantityObjectSignature.getRealMatrixSignature();
		((GenericQuantityObjectSignature)signature).setDimensions(new int[]{rows,cols});
		signature.setRealizationName("scilab");
	}
	
	public ScilabRealMatrix(double[][] arg0)
	{
		super();		
		try
		{
			sciObject = new ScilabDouble(arg0);
			sciEngine.put(sciVarName, sciObject);			
		} catch (JavasciException e)
		{
			log.error("Constructor - ",e);
		}
		signature = GenericQuantityObjectSignature.getRealMatrixSignature();
		((GenericQuantityObjectSignature)signature).setDimensions(new int[]{arg0.length,arg0[0].length});
		signature.setRealizationName("scilab");
	}
	
	public ScilabRealMatrix(RealMatrix arg0)
	{
		super();
		if (arg0!=null)
		{
			if (arg0.getSignature().getRealizationName().equalsIgnoreCase("scilab"))
			{
				try
				{
					sciObject = new ScilabDouble(arg0.getNumberOfRows(),arg0.getNumberOfCols());;
					sciEngine.put(sciVarName, sciObject);
					String sciJob = sciVarName +" = " + ((ScilabQuantityObject)arg0).getVarName()+";";
					log.info(sciJob);
					sciEngine.exec(sciJob);
				} catch (JavasciException e)
				{
					log.error("Constructor - ",e);
				}
			}
			else
			{
				try
				{
					sciObject = new ScilabDouble(arg0.getNumberOfRows(),arg0.getNumberOfCols());;
					sciEngine.put(sciVarName, sciObject);
					for (int i=0;i<getNumberOfRows();i++)
						for (int j=0;j<getNumberOfCols();j++)
							setMatrixElement((RealNumber)arg0.getMatrixElement(i, j), i, j);
				} catch (JavasciException e)
				{
					log.error("Constructor - ",e);
				}
			}				

			signature = GenericQuantityObjectSignature.getRealMatrixSignature();
			signature.setRealizationName("scilab");					
			((GenericQuantityObjectSignature)signature).setDimensions(new int[]{arg0.getNumberOfRows(),
					arg0.getNumberOfCols()});
		}		
	}
	
	public int getNumberOfRows()
	{
		if (sciObject!=null)
			return sciObject.getHeight();
		else return 0;
	}
	
	public int getNumberOfCols()
	{
		if (sciObject!=null)
			return sciObject.getWidth();
		else return 0;
	}
	
  public QuantityObject getMatrixElement(int i, int j)
  {
  	if (sciObject!=null)
  	{
  		if (i<getNumberOfRows()&&j<getNumberOfCols()&&i>=0&&j>=0)
  		{
  			return new GenericRealNumber(sciObject.getRealPart()[i][j]);
  		}  		
  		else return null;
  	}
  	return null;
  }
	
	@Override
	public void setMatrixElement(RealNumber arg0, int i, int j)
	{
		if ((sciObject!=null)&&(arg0!=null))
		{  		
			if (i<=getNumberOfRows()&&j<=getNumberOfCols()&&i>=0&&j>=0)
  		{
				try
				{
					String sciJob;			
	  			sciJob = sciVarName+"("+(i+1)+","+(j+1)+")="+arg0.getValue();
	  			if (sciEngine.exec(sciJob))
	  			{
		  			log.info(sciJob);
		  			sciObject = (ScilabDouble) sciEngine.get(getVarName());
	  			}

				} catch (JavasciException e)
				{
					log.error("Set matrix element - ",e);
				}  				
  		}  		
		}		
	}
	
	public double[][] getDoubleArray()
	{
		if (sciObject!=null)
			return sciObject.getRealPart();
		else return null;
	}
	
	private static final Logger log = LoggerFactory.getLogger(ScilabRealMatrix.class);	
}
